﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace SMSPanasonic.Business
{
    public static class Extensions
    {
        #region Extension for string
        public static string ToHex(this string value, Encoding enc)
        {
            // Encode the array of chars.
            StringBuilder returnString = new StringBuilder(string.Empty);
            foreach (var byteValue in enc.GetBytes(value))
                returnString.Append(String.Format("{0:X2}", byteValue));
            return returnString.ToString();
        }
        /// <summary>
        /// Nâng hoa ký tự đầu tiên của một xâu
        /// </summary>
        public static string UppercaseFirstLetter(this string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                char[] array = value.ToCharArray();
                array[0] = char.ToUpper(array[0]);
                return new string(array);
            }
            return value;
        }
        /// <summary>
        /// Đếm số từ của một xâu
        /// </summary>
        public static int WordCount(this string value)
        {
            return value.Split(new char[] { ' ', '.', '?', ',', '!', ':' }, StringSplitOptions.RemoveEmptyEntries).Length;
        }
        /// <summary>
        /// Kiểm tra một xâu có phải là số hay không. Trả về true nếu là số, không thì ngược lại
        /// </summary>
        public static bool IsNumeric(this string value)
        {
            double output;
            return double.TryParse(value, out output);
        }
        /// <summary>
        /// Kiểm tra một xâu có phải là Email không
        /// </summary>
        public static bool IsEmail(this string value)
        {
            Regex reg = new Regex(@"^[a-z0-9_]+(?:\.[a-z0-9]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", RegexOptions.IgnoreCase);
            try
            {
                return reg.IsMatch(value);
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// Kiểm tra một xâu có phải là URL không
        /// </summary>
        public static bool IsURL(this string value)
        {
            Regex reg = new Regex(@"^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~])*[^\.\,\)\(\s]$", RegexOptions.IgnoreCase);
            try
            {
                return reg.IsMatch(value);
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// Kiểm tra một xâu có phải là DateTime không
        /// </summary>
        public static bool IsDateTime(this string value)
        {
            DateTime dt;
            return DateTime.TryParse(value, out dt);
        }
        /// <summary>
        /// Kiểm tra một xâu có phải là số la mã không
        /// </summary>
        public static bool IsRomanNumber(this string value)
        {
            string[] soThuTuLaMa = {"I","II","III","IV","V","VI","VII","VIII","IX","X",
                                                 "XI","XII","XIII","XIV","XV","XVI","XVII","XVIII","XIX","XX",
                                                 "XXI","XXII","XXIII","XXIV","XXV","XXVI","XXVII","XXVIII","XXIX","XXX"};
            if (soThuTuLaMa.Contains(value)) return true;
            return false;
        }
        /// <summary>
        /// Chuẩn hóa một xâu
        /// </summary>
        public static string ToNormalString(this string value)
        {
            StringBuilder retValue = new StringBuilder(string.Empty);
            if (!string.IsNullOrEmpty(value))
            {
                string[] array = value.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string item in array)
                {
                    retValue.Append(item + " ");
                }
            }
            return retValue.ToString().Trim();
        }
        /// <summary>
        /// Chuẩn hóa 1 số điện thoại (ví dụ: 841682821740)
        /// </summary>
        public static string ToNormalPhoneNumber(this string value)
        {
            string normalPhoneNumber = string.Empty;
            foreach (char item in value)
            {
                if (item >= '0' && item <= '9')
                    normalPhoneNumber += item;
            }
            //Kiểm tra 2 ký tự đầu, nếu không phải là 84 thì xử lý
            if (!normalPhoneNumber.StartsWith("84"))
            {
                //Kiểm tra 1 ký tự đầu, nếu là ký tự 0 thì cắt đi
                if (normalPhoneNumber.StartsWith("0"))
                {
                    normalPhoneNumber = normalPhoneNumber.Substring(1);
                }
                //Thêm ký tự 84 vào trước
                normalPhoneNumber = "84" + normalPhoneNumber;
            }
            return normalPhoneNumber;
        }
        /// <summary>
        /// Chuyển một xâu tiếng Việt có dấu thành không dấu (Nguồn: internet)
        /// </summary>
        public static string ToVietnameseWithoutAccent(this string text)
        {
            if (!string.IsNullOrEmpty(text))
            {
                System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\p{IsCombiningDiacriticalMarks}+");
                string strFormD = text.Normalize(System.Text.NormalizationForm.FormD);
                return regex.Replace(strFormD, String.Empty).Replace('\u0111', 'd').Replace('\u0110', 'D');
            }
            return text;
        }
        /// <summary>
        /// Mã hóa MD5
        /// </summary>
        public static string ToMD5Hash(this string value)
        {
            Byte[] originalBytes;
            Byte[] encodedBytes;
            MD5 md5 = new MD5CryptoServiceProvider();
            originalBytes = UTF8Encoding.Default.GetBytes(value);
            encodedBytes = md5.ComputeHash(originalBytes);
            //Convert encoded bytes back to a 'readable' string
            return BitConverter.ToString(encodedBytes).Replace("-", string.Empty);
        }

        /// <summary>
        /// Mã hóa dữ liệu theo RSA
        /// </summary>
        /// <param name="_dataEncrypt">Dữ liệu cần mã hóa</param>
        /// <returns>Dữ liệu đã mã hóa</returns>
        public static string ToRsaEncrypt(this string value, string publicKeyPath)
        {
            RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider();
            using (System.IO.StreamReader reader = new System.IO.StreamReader(publicKeyPath))
            {
                string publicOnlyKeyXML = reader.ReadToEnd();
                rsa.FromXmlString(publicOnlyKeyXML);
                reader.Close();
            }
            //read plaintext, encrypt it to ciphertext

            byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(value);
            byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
            return Convert.ToBase64String(cipherbytes);
        }

        /// <summary>
        /// Giải mã dữ liệu theo RSA
        /// </summary>
        /// <param name="_dataDecrypt"></param>
        /// <returns></returns>
        public static string ToRsaDecrypt(this string value, string privateKeyPath)
        {
            RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider();
            byte[] cipherbytes = Convert.FromBase64String(value);
            using (System.IO.StreamReader reader = new System.IO.StreamReader(privateKeyPath))
            {
                string publicPrivateKeyXML = reader.ReadToEnd();
                rsa.FromXmlString(publicPrivateKeyXML);
                reader.Close();
            }
            //read ciphertext, decrypt it to plaintext
            byte[] plain = rsa.Decrypt(cipherbytes, false);
            return System.Text.Encoding.UTF8.GetString(plain);

        }

        /// <summary>
        /// Tạo đối tượng RSACryptoServiceProvider
        /// </summary>
        /// <returns></returns>
        private static RSACryptoServiceProvider CreateRSACryptoServiceProvider()
        {
            CspParameters cspParams = new CspParameters(1, "VTCOnlinePassContainerKey");
            cspParams.Flags = CspProviderFlags.UseUserProtectedKey;
            cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
            return new RSACryptoServiceProvider(cspParams);
        }
        #endregion

        #region Extension for decimal
        public static decimal Round(this decimal value)
        {
            return Math.Round(value, MidpointRounding.AwayFromZero);
        }
        #endregion

        #region Extension for DateTime
        /// <summary>
        /// Lấy ngày đầu tiên của tháng
        /// </summary>
        public static DateTime GetFirstDayOfMonth(this DateTime value)
        {
            return new DateTime(value.Year, value.Month, 1, 0, 0, 0);
        }
        /// <summary>
        /// Lấy ngày cuối cùng của tháng
        /// </summary>
        public static DateTime GetLastDayOfMonth(this DateTime value)
        {
            return value.GetFirstDayOfMonth().AddMonths(1).AddSeconds(-1);
        }

        /// <summary>
        /// Cộng ngày tháng với quy ước 1 tháng có 30 ngày
        /// </summary>
        /// <param name="values">Số ngày cần cộng thêm</param>
        /// <returns></returns>
        public static DateTime AddDaysRound30(this DateTime d, int values)
        {
            int months = (values - 1) / 30;
            int days = (values - 1) % 30;
            DateTime retValue = d.AddMonths(months);
            if (retValue.Day + days <= new DateTime(retValue.Year, retValue.Month, 1).AddMonths(1).AddDays(-1).Day)
            {
                retValue = retValue.AddDays(days);
            }
            else
            {
                days = retValue.Day + days - 30;
                retValue = new DateTime(retValue.Year, retValue.Month + 1, days);
            }
            return retValue;
        }

        /// <summary>
        /// Trả về số ngày của tháng với quy ước một tháng có 30 ngày.
        /// </summary>
        public static int GetDayRound30(this DateTime d)
        {
            DateTime tmp = new DateTime(d.Year, d.Month, 1, 0, 0, 0);
            tmp = tmp.AddMonths(1).AddDays(-1);
            if (tmp.Day == d.Day) return 30;
            return d.Day;
        }
        #endregion
    }
}
